/**
 * Copyright 2011 The Apache Software Foundation
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package enterprise.web_jpa_war.servlet;

import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import enterprise.web_jpa_war.entity.Person;
import enterprise.web_jpa_war.entity.Role;
import enterprise.web_jpa_war.entity.RoleRelationship;

/**
 * Servlet implementation class MaintainPersonServlet
 */
public class MaintainPersonServlet extends AbstractServlet {
	

	private static final String SQL_UPDATE_PERSON = "UPDATE PERSON p " +
		    			"SET p.LAST_NAME = ?, p.FIRST_NAME = ?, p.ACCOUNT_NAME = UPPER(?), p.PASSWORD = ? " +
		    			"WHERE p.ID = ? ";
	private static final String SQL_QUERY_PERSON = 
		"SELECT p.*, pr.PERSON_ROLE_ID, pr.ROLE_NAME FROM PERSON p JOIN PERSON_ROLES pr ON(p.ID = pr.PERSON_ID) " +
		"WHERE p.ID = ? ";
	
	private static final String SQL_DELETE_PERSON_ROLES =
		"DELETE FROM PERSON_ROLES WHERE PERSON_ID = ?";
	
	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		Long id = new Long(request.getParameter("id"));
		
		Connection connection = null;
		PreparedStatement statement = null;
		ResultSet resultSet = null;
		Person person = null;
		List<RoleRelationship> roleRelationships = null;
		
		try {
			connection = this.getConnection();
		
			statement = connection.prepareStatement(SQL_QUERY_PERSON);
			statement.setLong(1, id);
			resultSet = statement.executeQuery();
			
			if(resultSet.next()){
				person = new Person();
				person.setId(resultSet.getLong("ID"));
				person.setFirstName(resultSet.getString("FIRST_NAME"));
				person.setLastName(resultSet.getString("LAST_NAME"));
				person.setAccountName(resultSet.getString("ACCOUNT_NAME"));
				person.setPassword(resultSet.getString("PASSWORD"));
				
				roleRelationships = new ArrayList<RoleRelationship>();
				
				roleRelationships.add(generateRoleRelationship(resultSet));
				while(resultSet.next()){
					roleRelationships.add(generateRoleRelationship(resultSet));
				}
				
				person.setRoleRelationships(roleRelationships);
			}
		} catch (SQLException e) {
			e.printStackTrace();
			throw new RuntimeException("Maintain person(id:" + id + ")", e);
		}
		
		request.setAttribute("person", person);
		request.setAttribute("roles", getRolesString(person));
		request.getRequestDispatcher("/person/MaintainPerson.jsp").forward(request, response);
	}
	
	private String getRolesString(Person person){
		StringBuffer rolesString = new StringBuffer();
		List<Role> roles = person.getRoles();
		Role role = null;
		for(int a = 0; a < roles.size(); a++){
			role = roles.get(a);
			if(a == 0){
				rolesString.append("'" + role.getName() + "'");
			} else{
				rolesString.append(", '" + role.getName() + "'");
			}
		}
		return rolesString.toString();
	}

	private RoleRelationship generateRoleRelationship(ResultSet resultSet) throws SQLException {
		RoleRelationship roleRelationship;
		Role role;
		role = new Role();
		role.setId(resultSet.getLong("PERSON_ROLE_ID"));
		role.setName(resultSet.getString("ROLE_NAME"));
		roleRelationship = new RoleRelationship();
		roleRelationship.setRole(role);
		
		return roleRelationship;
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    	Long id = new Long(request.getParameter("id"));
    	String lastName = request.getParameter("lastName");
    	String firstName = request.getParameter("firstName");
    	String accountName = request.getParameter("accountName");
    	String[] roleNames = request.getParameterValues("roleName");
    	String password = request.getParameter("password");
    	
    	Connection connection = null;
    	PreparedStatement statement = null;
    	
    	try {
			connection = this.getConnection();
	    	connection.setAutoCommit(false);
	    	
	    	//1. update person
	    	statement = connection.prepareStatement(SQL_UPDATE_PERSON);
	    	
	    	statement.setString(1, lastName);
	    	statement.setString(2, firstName);
	    	statement.setString(3, accountName);
	    	statement.setString(4, password);
	    	statement.setLong(5, id);
	    	statement.execute();
	    	
	    	//2. delete roles
	    	statement = connection.prepareStatement(SQL_DELETE_PERSON_ROLES);
	    	statement.setLong(1, id);
	    	statement.execute();
	    	
	    	//3. re-insert selected roles
	    	List<Long> roleIds = this.getRoleIds(connection, roleNames);
	    	this.insertPersonRolesRelationship(accountName, roleNames, id, roleIds, connection);
	    	
    	} catch (SQLException e) {
			e.printStackTrace();
			throw new RuntimeException("maintain for person(id:" + id + ") failed", e);
		} finally {
			closeStatement(statement);
			closeConnection(connection);
		}
        //Forward to the jsp page for rendering
        request.getRequestDispatcher("ListPerson").forward(request, response);
	}

}
